#include "block_factory.h"

BlockFactory::BlockFactory(unsigned int blockSize)
	: chainFactory(blockSize){
	this->blockSize = blockSize; 
}

BlockFactory::~BlockFactory(){
}

Block* BlockFactory::operator()(char* data,const RegisterFactory& factory){
	char *temp = data;
	Block *block;;
	unsigned short quantity;
	char status;
	
	memcpy( (char*)&status,temp,sizeof(char));
	temp+=sizeof(char);
	memcpy( (char*)&quantity,temp,sizeof(unsigned short));
	temp+=sizeof(unsigned short);
	
	if(Block::isChainedBit(status))
		block = new Block(chainFactory,blockSize);
	else
		block = new Block(factory,blockSize);

	block->setStatus(status);
	
	unsigned short temp_offset;
	unsigned short temp_num;	
	for(unsigned short i=0;i<quantity;i++){
		memcpy(&temp_num,temp,sizeof(unsigned short));
		temp+=sizeof(unsigned short);
		memcpy(&temp_offset,temp,sizeof(unsigned short));
		char* regBytes = data + temp_offset;
		
		/* La deserializacion depende si es o no parte de una cadena */
		Register* reg;
		if(!block->isChained()){
			reg = factory(regBytes);
		}else{
			chainFactory.setCurrentOffset(temp_offset);
			reg = chainFactory(regBytes);
		}
		
		//Respeta el nro de reg que tenia
		block->addRegister(*reg, temp_num);		
		delete reg;
		temp+=sizeof(unsigned short);
	}
			
	return block;
}
		
/* Dado un bloque y un array de bytes serializa la clase Bloque en el array de bytes */
char* BlockFactory::operator ()(Block &block, char* data)const{
	char* temp = data;
	unsigned short quantity = block.getQuantity();	
	char status = block.getStatus();
	
	memcpy(temp, &status, sizeof(char));
	temp += sizeof(char);
	memcpy(temp, &quantity, sizeof(unsigned short));
	temp+=sizeof(unsigned short);
	
	for(unsigned short i=0;i<block.getQuantity();i++){
		unsigned short regNum = block.getRegNumber(i);
		memcpy(temp, &(regNum), sizeof(unsigned short));
		temp+=sizeof(unsigned short);
		unsigned short regOffset = block.getRegOffset(i);
		memcpy(temp, &(regOffset), sizeof(unsigned short));
		temp+=sizeof(unsigned short);
	}

	/* Da lo mismo tener bits random y todos en cero
	   memset(temp,0,block.getFree());
	*/
	temp+=block.getFree();
			
	for(int i=block.getQuantity()-1;i>=0;i--){
		int size;
		if (i!=0){
			size = block.getRegOffset(i-1) - block.getRegOffset(i);
		}else{
			size = blockSize - block.getRegOffset(i);
		}				
		char* regBytes = block.getReg(i);
		memcpy(temp,regBytes,size);

		temp+=size;
	}
	return temp;
}
